| 1 | import AppKit |
| 2 | |
| 3 | // Before macOS 26 the system draws the supplied silhouette as it is; unlike iOS |
| 4 | // it does not mask an opaque master. Derive the Mac's rounded tile on Apple's |
| 5 | // 824-on-1024 grid from the full-bleed square master, the iPhone's. Not from |
| 6 | // Resources/AppIcon.png: that one is already rounded onto the grid, and |
| 7 | // drawing it into the grid again left the artwork at 664 of 1024, small in the |
| 8 | // Dock beside every other app. macOS 26 and later use Assets.car instead |
| 9 | // (bundle-mac.py), where the system applies the mask. |
| 10 | let native = URL(fileURLWithPath: #filePath).standardizedFileURL |
| 11 | .deletingLastPathComponent().deletingLastPathComponent() |
| 12 | let resources = native.appendingPathComponent("apple/Sources/CallsMac/Resources") |
| 13 | let master = native.appendingPathComponent("ios/Assets.xcassets/AppIcon.appiconset/AppIcon.png") |
| 14 | guard let source = NSImage(contentsOf: master), |
| 15 | let bitmap = NSBitmapImageRep(bitmapDataPlanes: nil, pixelsWide: 1024, pixelsHigh: 1024, |
| 16 | bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, |
| 17 | colorSpaceName: .deviceRGB, bytesPerRow: 0, bitsPerPixel: 0), |
| 18 | let context = NSGraphicsContext(bitmapImageRep: bitmap) |
| 19 | else { fatalError("Cannot load or render Calls's icon") } |
| 20 | NSGraphicsContext.saveGraphicsState() |
| 21 | NSGraphicsContext.current = context |
| 22 | context.imageInterpolation = .high |
| 23 | let tile = NSRect(x: 100, y: 100, width: 824, height: 824) |
| 24 | NSBezierPath(roundedRect: tile, xRadius: 184, yRadius: 184).addClip() |
| 25 | source.draw(in: tile, from: .zero, operation: .copy, fraction: 1) |
| 26 | NSGraphicsContext.restoreGraphicsState() |
| 27 | guard let png = bitmap.representation(using: .png, properties: [:]) else { |
| 28 | fatalError("Cannot encode Calls's icon") |
| 29 | } |
| 30 | try png.write(to: resources.appendingPathComponent("MacIcon.png")) |
| 31 | |