// Regenerates the app icon PNGs from the same geometry as Branding/logo.svg. // // cd apps/ios // swift Branding/make-icons.swift Koins/Assets.xcassets/AppIcon.appiconset // // iOS cannot use SVG for app icons, so the SVG is the source artwork and this // script produces the raster the asset catalog needs. It also writes // Branding/logo-light.png (white ground, black mark). import AppKit import CoreGraphics import Foundation // Draws the same geometry as Branding/logo.svg with CoreGraphics, because iOS // app icons must be raster images. func drawIcon(size: CGFloat, inverted: Bool = false) -> CGImage? { let scale = size / 1024.0 let colorSpace = CGColorSpaceCreateDeviceRGB() guard let context = CGContext(data: nil, width: Int(size), height: Int(size), bitsPerComponent: 8, bytesPerRow: 0, space: colorSpace, bitmapInfo: CGImageAlphaInfo.noneSkipLast.rawValue) else { return nil } let background = inverted ? NSColor.white : NSColor.black let foreground = inverted ? NSColor.black : NSColor.white context.setFillColor(background.cgColor) context.fill(CGRect(x: 0, y: 0, width: size, height: size)) context.setStrokeColor(foreground.cgColor) context.setLineWidth(118 * scale) context.setLineCap(.butt) context.setLineJoin(.miter) func point(_ x: CGFloat, _ y: CGFloat) -> CGPoint { // SVG y grows downwards, CoreGraphics grows upwards. CGPoint(x: x * scale, y: size - y * scale) } // Left leg continuing into the central V (one path, so the top corner is a // clean miter rather than two overlapping strokes). context.beginPath() context.move(to: point(279, 758)) context.addLine(to: point(279, 280)) context.addLine(to: point(512, 640)) context.strokePath() // Right leg, mirrored. context.beginPath() context.move(to: point(745, 758)) context.addLine(to: point(745, 280)) context.addLine(to: point(512, 640)) context.strokePath() // Full-width bar across the base. context.beginPath() context.move(to: point(220, 699)) context.addLine(to: point(804, 699)) context.strokePath() return context.makeImage() } func write(_ image: CGImage, to path: String) { let rep = NSBitmapImageRep(cgImage: image) guard let data = rep.representation(using: .png, properties: [:]) else { return } try? data.write(to: URL(fileURLWithPath: path)) print("wrote \(path)") } let outputDir = CommandLine.arguments.count > 1 ? CommandLine.arguments[1] : "/tmp" try? FileManager.default.createDirectory(atPath: outputDir, withIntermediateDirectories: true) if let icon = drawIcon(size: 1024) { write(icon, to: "\(outputDir)/AppIcon-1024.png") } // A light variant, handy for other surfaces (white background, black mark). if let light = drawIcon(size: 1024, inverted: true) { write(light, to: "\(outputDir)/AppIcon-light-1024.png") }