#!/usr/bin/env swift // Generates the G-ART app icon (a gradient tile with a white waveform) // and writes AppIcon.icns. Run from the repo root: // swift MacApp/make_icon.swift import AppKit import CoreGraphics import Foundation let size: CGFloat = 1024 let image = NSImage(size: NSSize(width: size, height: size)) image.lockFocus() guard let ctx = NSGraphicsContext.current?.cgContext else { print("no ctx"); exit(1) } // Background: vertical gradient blue → indigo. let colors = [ NSColor(calibratedRed: 0.0, green: 0.48, blue: 1.0, alpha: 1).cgColor, NSColor(calibratedRed: 0.30, green: 0.20, blue: 0.85, alpha: 1).cgColor, ] let space = CGColorSpaceCreateDeviceRGB() if let grad = CGGradient(colorsSpace: space, colors: colors as CFArray, locations: [0, 1]) { ctx.drawLinearGradient(grad, start: CGPoint(x: 0, y: size), end: CGPoint(x: size, y: 0), options: []) } // Rounded-corner mask (squircle-ish). let rect = CGRect(x: 0, y: 0, width: size, height: size) let corner: CGFloat = 230 let path = CGPath(roundedRect: rect, cornerWidth: corner, cornerHeight: corner, transform: nil) ctx.addPath(path) ctx.clip() // White waveform: several vertical bars of varying height. ctx.setFillColor(NSColor.white.cgColor) let barW: CGFloat = 70 let gap: CGFloat = 45 let totalW = 5 * barW + 4 * gap let startX = (size - totalW) / 2 let heights: [CGFloat] = [240, 500, 700, 500, 240] let baseY = (size - 700) / 2 for (i, h) in heights.enumerated() { let x = startX + CGFloat(i) * (barW + gap) let bar = CGRect(x: x, y: baseY, width: barW, height: h) let barPath = CGPath(roundedRect: bar, cornerWidth: barW / 2, cornerHeight: barW / 2, transform: nil) ctx.addPath(barPath) ctx.fillPath() } image.unlockFocus() // Convert to 1024 PNG temp, then build .icns via iconutil. let outDir = FileManager.default.temporaryDirectory.appendingPathComponent("gart_icon") try? FileManager.default.removeItem(at: outDir) try FileManager.default.createDirectory(at: outDir, withIntermediateDirectories: true) let pngSizes = [16, 32, 64, 128, 256, 512, 1024] let iconset = outDir.appendingPathComponent("AppIcon.iconset") try FileManager.default.createDirectory(at: iconset, withIntermediateDirectories: true) func write(_ size: Int, _ name: String) throws { let w = NSSize(width: size, height: size) let rep = NSBitmapImageRep(bitmapDataPlanes: nil, pixelsWide: size, pixelsHigh: size, bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, colorSpaceName: .deviceRGB, bytesPerRow: 0, bitsPerPixel: 0)! rep.size = w NSGraphicsContext.saveGraphicsState() NSGraphicsContext.current = NSGraphicsContext(bitmapImageRep: rep) image.draw(in: NSRect(origin: .zero, size: w), from: .zero, operation: .sourceOver, fraction: 1) NSGraphicsContext.restoreGraphicsState() let data = rep.representation(using: .png, properties: [:])! try data.write(to: iconset.appendingPathComponent(name)) } try write(16, "icon_16x16.png") try write(32, "icon_16x16@2x.png") try write(32, "icon_32x32.png") try write(64, "icon_32x32@2x.png") try write(128, "icon_128x128.png") try write(256, "icon_128x128@2x.png") try write(256, "icon_256x256.png") try write(512, "icon_256x256@2x.png") try write(512, "icon_512x512.png") try write(1024, "icon_512x512@2x.png") let process = Process() process.executableURL = URL(fileURLWithPath: "/usr/bin/iconutil") process.arguments = ["-c", "icns", iconset.path, "-o", "MacApp/Assets/AppIcon.icns"] try process.run() process.waitUntilExit() print("Icon written to MacApp/Assets/AppIcon.icns")