grammargem/scripts/make-icon.swift
BigMarc 197df3298f Customizable shortcuts, app icon, restore-clipboard preference
- Shortcuts screen now records custom global hotkeys (Fix + Ask), persisted and
  re-registered live via Preferences + Combine.
- Add branded AppIcon.icns (gold nib on ink), wired into Info.plist + build.sh.
- "Restore my clipboard after a fix" preference now drives the clipboard fallback.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 14:59:15 +02:00

68 lines
2.6 KiB
Swift

#!/usr/bin/env swift
// Generates AppIcon.iconset (PNGs) for GrammaGem — a gold pen-nib on the ink
// brand square. Run from mac/: swift scripts/make-icon.swift
// Then: iconutil -c icns AppIcon.iconset -o AppSupport/AppIcon.icns
import AppKit
import Foundation
let ink = NSColor(red: 0x10 / 255.0, green: 0x23 / 255.0, blue: 0x1B / 255.0, alpha: 1)
let gold = NSColor(red: 0xC9 / 255.0, green: 0xA2 / 255.0, blue: 0x4B / 255.0, alpha: 1)
func png(size: Int) -> Data {
let S = CGFloat(size)
let rep = NSBitmapImageRep(
bitmapDataPlanes: nil, pixelsWide: size, pixelsHigh: size,
bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false,
colorSpaceName: .deviceRGB, bytesPerRow: 0, bitsPerPixel: 0)!
let ctx = NSGraphicsContext(bitmapImageRep: rep)!
NSGraphicsContext.saveGraphicsState()
NSGraphicsContext.current = ctx
let g = ctx.cgContext
// Brand square (rounded).
let rrect = CGPath(roundedRect: CGRect(x: 0, y: 0, width: S, height: S),
cornerWidth: S * 0.22, cornerHeight: S * 0.22, transform: nil)
g.addPath(rrect); g.setFillColor(ink.cgColor); g.fillPath()
// Gold nib (downward triangle), coordinates are y-up.
let tri = CGMutablePath()
tri.move(to: CGPoint(x: 0.18 * S, y: 0.78 * S))
tri.addLine(to: CGPoint(x: 0.82 * S, y: 0.78 * S))
tri.addLine(to: CGPoint(x: 0.50 * S, y: 0.10 * S))
tri.closeSubpath()
g.addPath(tri); g.setFillColor(gold.cgColor); g.fillPath()
// Center slit.
g.setStrokeColor(ink.cgColor)
g.setLineWidth(max(1, S * 0.05)); g.setLineCap(.round)
g.move(to: CGPoint(x: 0.50 * S, y: 0.20 * S))
g.addLine(to: CGPoint(x: 0.50 * S, y: 0.60 * S))
g.strokePath()
// Vent hole.
g.setFillColor(ink.cgColor)
let r = S * 0.055
g.addEllipse(in: CGRect(x: 0.50 * S - r, y: 0.64 * S - r, width: 2 * r, height: 2 * r))
g.fillPath()
NSGraphicsContext.restoreGraphicsState()
return rep.representation(using: .png, properties: [:])!
}
let fm = FileManager.default
let dir = "AppIcon.iconset"
try? fm.removeItem(atPath: dir)
try! fm.createDirectory(atPath: dir, withIntermediateDirectories: true)
let specs: [(String, 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 (name, size) in specs {
try! png(size: size).write(to: URL(fileURLWithPath: "\(dir)/\(name).png"))
}
print("wrote \(specs.count) icon images to \(dir)")