// Renders the CocotteAI app icon (✦ mark on the rose brand background) and writes // a full .iconset directory. Run on macOS: `swift make-icon.swift `. // The shell packager then `iconutil -c icns`s it. Colors match DesignTokens' rose // accent (r7 #c75872) over the dark canvas (#100c0e). import AppKit // Initialize the shared app so AppKit font/graphics services are available in this // CLI context (no run loop needed — we never call run()). _ = NSApplication.shared let outDir = CommandLine.arguments.count > 1 ? CommandLine.arguments[1] : "AppIcon.iconset" try? FileManager.default.createDirectory(atPath: outDir, withIntermediateDirectories: true) func color(_ hex: UInt32) -> NSColor { NSColor(srgbRed: CGFloat((hex >> 16) & 0xff) / 255, green: CGFloat((hex >> 8) & 0xff) / 255, blue: CGFloat(hex & 0xff) / 255, alpha: 1) } /// Draw the icon at `size` px (square) into a fresh bitmap context and return PNG /// data. Draws straight into an NSBitmapImageRep context (not NSImage.lockFocus), /// which is the reliable path in a command-line tool. func render(_ size: Int) -> Data { let s = CGFloat(size) guard let rep = NSBitmapImageRep( bitmapDataPlanes: nil, pixelsWide: size, pixelsHigh: size, bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, colorSpaceName: .deviceRGB, bytesPerRow: 0, bitsPerPixel: 0) else { fatalError("bitmap alloc failed at \(size)") } NSGraphicsContext.saveGraphicsState() defer { NSGraphicsContext.restoreGraphicsState() } NSGraphicsContext.current = NSGraphicsContext(bitmapImageRep: rep) // Rounded-rect canvas with a subtle rose vertical gradient (macOS Big Sur look: // full-bleed rounded square, the system masks corners on display). let rect = NSRect(x: 0, y: 0, width: s, height: s) let radius = s * 0.22 let path = NSBezierPath(roundedRect: rect, xRadius: radius, yRadius: radius) path.addClip() NSGradient(colors: [color(0x1c1619), color(0x100c0e)])?.draw(in: rect, angle: -90) // The ✦ mark, rose accent, centered. let fontSize = s * 0.62 let attrs: [NSAttributedString.Key: Any] = [ .font: NSFont.systemFont(ofSize: fontSize, weight: .semibold), .foregroundColor: color(0xc75872), ] let str = NSAttributedString(string: "✦", attributes: attrs) let bounds = str.size() str.draw(at: NSPoint(x: (s - bounds.width) / 2, y: (s - bounds.height) / 2)) guard let png = rep.representation(using: .png, properties: [:]) else { fatalError("PNG encode failed at size \(size)") } return png } // Standard macOS iconset matrix. let specs: [(name: String, size: Int)] = [ ("icon_16x16", 16), ("icon_16x16@2x", 32), ("icon_32x32", 32), ("icon_32x32@2x", 64), ("icon_128x128", 128), ("icon_128x128@2x", 256), ("icon_256x256", 256), ("icon_256x256@2x", 512), ("icon_512x512", 512), ("icon_512x512@2x", 1024), ] for spec in specs { let url = URL(fileURLWithPath: "\(outDir)/\(spec.name).png") try! render(spec.size).write(to: url) } FileHandle.standardError.write("wrote \(specs.count) icons to \(outDir)\n".data(using: .utf8)!)