Files

96 lines
3.6 KiB
Swift

#!/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")