// Draws AppIcon.png, the Viewer's icon: ProdDash's 2×2 tile mark on a // display, so the Viewer and ProdDash itself tell apart in Finder and the // Dock. Run it again only to change the icon; build.sh uses the PNG. // // swift Resources/make-icon.swift Resources/AppIcon.png import AppKit let side = 1024 let output = CommandLine.arguments.dropFirst().first ?? "AppIcon.png" guard let bitmap = NSBitmapImageRep( bitmapDataPlanes: nil, pixelsWide: side, pixelsHigh: side, bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, colorSpaceName: .deviceRGB, bytesPerRow: 0, bitsPerPixel: 0), let context = NSGraphicsContext(bitmapImageRep: bitmap) else { fatalError("no bitmap") } NSGraphicsContext.current = context let g = context.cgContext // Top-left origin, as the measurements below are written. g.translateBy(x: 0, y: CGFloat(side)) g.scaleBy(x: 1, y: -1) func color(_ hex: UInt32, _ alpha: CGFloat = 1) -> CGColor { CGColor(srgbRed: CGFloat((hex >> 16) & 0xff) / 255, green: CGFloat((hex >> 8) & 0xff) / 255, blue: CGFloat(hex & 0xff) / 255, alpha: alpha) } func rounded(_ rect: CGRect, _ radius: CGFloat) -> CGPath { CGPath(roundedRect: rect, cornerWidth: radius, cornerHeight: radius, transform: nil) } func fill(_ path: CGPath, _ fillColor: CGColor) { g.addPath(path); g.setFillColor(fillColor); g.fillPath() } // The body: Apple's icon grid — an 824-point rounded square, centred, on the // soft shadow macOS icons sit on. ProdDash's own near-black. let body = CGRect(x: 100, y: 100, width: 824, height: 824) let bodyPath = rounded(body, 185) g.saveGState() g.setShadow(offset: CGSize(width: 0, height: 12), blur: 28, color: color(0x000000, 0.35)) fill(bodyPath, color(0x0b0e12)) g.restoreGState() g.saveGState() g.addPath(bodyPath); g.clip() let shade = CGGradient(colorsSpace: CGColorSpace(name: CGColorSpace.sRGB), colors: [color(0x1b222b), color(0x0a0d11)] as CFArray, locations: [0, 1])! g.drawLinearGradient(shade, start: CGPoint(x: 0, y: body.minY), end: CGPoint(x: 0, y: body.maxY), options: []) g.restoreGState() g.addPath(rounded(body.insetBy(dx: 1.5, dy: 1.5), 183.5)) g.setStrokeColor(color(0xffffff, 0.08)); g.setLineWidth(3); g.strokePath() // The display: bezel, screen, neck and foot. let bezel = CGRect(x: 212, y: 250, width: 600, height: 410) let metal = color(0x3a434f) fill(rounded(CGRect(x: 474, y: 650, width: 76, height: 84), 8), metal) fill(rounded(CGRect(x: 372, y: 724, width: 280, height: 36), 18), color(0x4a5462)) fill(rounded(bezel, 44), metal) let screen = bezel.insetBy(dx: 22, dy: 22) fill(rounded(screen, 26), color(0x0c1015)) // ProdDash's mark on the screen: three outlined tiles and the lit one. let padding: CGFloat = 46, gap: CGFloat = 30 let tileW = (screen.width - padding * 2 - gap) / 2 let tileH = (screen.height - padding * 2 - gap) / 2 for (column, row) in [(0, 0), (1, 0), (0, 1), (1, 1)] { let tile = CGRect(x: screen.minX + padding + CGFloat(column) * (tileW + gap), y: screen.minY + padding + CGFloat(row) * (tileH + gap), width: tileW, height: tileH) if column == 1 && row == 1 { fill(rounded(tile, 22), color(0x2fe39a)) } else { let inset = tile.insetBy(dx: 5, dy: 5) fill(rounded(inset, 18), color(0x121820)) g.addPath(rounded(inset, 18)); g.setStrokeColor(color(0x3d4652)); g.setLineWidth(10); g.strokePath() } } guard let png = bitmap.representation(using: .png, properties: [:]) else { fatalError("no png") } try png.write(to: URL(fileURLWithPath: output)) print("wrote \(output)")